package com.qqt.csr.order.service;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qqt.csr.common.exception.BaseException;
import com.qqt.csr.common.session.SessionContextHolder;
import com.qqt.csr.common.vo.resp.PageResponse;
import com.qqt.csr.order.entity.WorkOrder;
import com.qqt.csr.order.entity.WorkOrderEvent;
import com.qqt.csr.order.enums.WorkOrderStatusEnum;
import com.qqt.csr.order.mapper.WorkOrderMapper;
import com.qqt.csr.order.vo.req.QueryPageWorkOrderReqVO;
import com.qqt.csr.order.vo.resp.CsWorkOrderCountRespVO;
import com.qqt.csr.order.vo.resp.WorkOrderDetailRespVO;
import com.qqt.csr.order.vo.resp.WorkOrderRespVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author
 */
@Slf4j
@Service
public class WorkOrderService extends ServiceImpl<WorkOrderMapper, WorkOrder> {

    @Autowired
    private WorkOrderEventService workOrderEventService;

    /**
     * 分页查询工单列表
     *
     * @param reqVO {@link QueryPageWorkOrderReqVO} 查询参数
     * @return {@link IPage<WorkOrderRespVO>} 分页数据
     */
    public PageResponse<WorkOrderRespVO> page(QueryPageWorkOrderReqVO reqVO) {
        // 设置当前用户id
        reqVO.setCurrentUserId(SessionContextHolder.getHeaderInfo().getUserId().toString());
        IPage<WorkOrderRespVO> page = baseMapper.page(new Page<>(reqVO.getPage(), reqVO.getPageSize()), reqVO);
        // 挂起状态数据回溯状态
        List<WorkOrderRespVO> records = page.getRecords();
        List<WorkOrderRespVO> suspendedRecords = records.stream()
                .filter(item -> WorkOrderStatusEnum.SUSPENDED.getStatus().equals(item.getStatus()))
                .toList();
        List<Long> suspendedIds = suspendedRecords.stream().map(WorkOrderRespVO::getId).toList();
        List<WorkOrderEvent> events = workOrderEventService.listLastEvent(suspendedIds, WorkOrderStatusEnum.SUSPENDED);
        if (events != null && !events.isEmpty()) {
            Map<Long, WorkOrderRespVO> recordMap = records.stream()
                    .collect(Collectors.toMap(WorkOrderRespVO::getId, item -> item));
            // 装载
            for (WorkOrderEvent event : events) {
                WorkOrderRespVO record = recordMap.get(event.getOrderId());
                if (record != null) {
                    record.setIsSuspended(1);
                    record.setStatus(event.getFrom());
                }
            }
        }
        return new PageResponse<>(page.getTotal(), reqVO.getPageSize(), reqVO.getPage(), records);
    }

    /**
     * 工单详情
     *
     * @param orderId {@link Long} 工单id
     * @return {@link WorkOrderDetailRespVO} 工单详情
     */
    public WorkOrderDetailRespVO detail(Long orderId) {
        if (orderId == null) {
            return null;
        }
        WorkOrderDetailRespVO detail = baseMapper.detail(orderId);
        if (detail == null) {
            return null;
        }
        // 挂起状态数据回溯状态
        if (WorkOrderStatusEnum.SUSPENDED.getStatus().equals(detail.getStatus())) {
            // 回溯
            WorkOrderEvent event = workOrderEventService.lastEvent(detail.getId(), WorkOrderStatusEnum.SUSPENDED);
            if (event == null) {
                log.error("工单状态事件异常, orderId: {}", detail.getId());
                throw new BaseException("工单状态事件异常, orderId:" + detail.getId());
            }
            detail.setIsSuspended(1);
            detail.setStatus(event.getFrom());
        }
        return detail;
    }

    /**
     * 根据工单id或工单编码查询工单信息
     *
     * @param orderId
     * @param orderCode
     * @return
     */
    public WorkOrder getWorkOrder(Long orderId, String orderCode) {
        if (orderId == null && StringUtils.isBlank(orderCode)) {
            return null;
        }
        return this.lambdaQuery().select()
                .eq(orderId != null, WorkOrder::getId, orderId)
                .eq(StringUtils.isNotBlank(orderCode), WorkOrder::getOrderCode, orderCode)
                .one();
    }

    /**
     * 保存工单
     *
     * @param order
     */
    public void insert(WorkOrder order) {
        if (order == null) {
            return;
        }
        this.save(order);
    }

    /**
     * 更新工单
     *
     * @param order
     */
    public void update(WorkOrder order) {
        if (order == null || order.getId() == null) {
            return;
        }
        if (order.isDeleted()) {
            this.removeById(order.getId());
        } else {
            this.updateById(order);
        }
    }

    /**
     * 获取用于计算已耗时时长的工单
     *
     * @param lastId
     * @return
     */
    public List<WorkOrder> getListForCalculatingElapsedTime(Long lastId, int limit) {
        return this.lambdaQuery()
                .select(WorkOrder::getId, WorkOrder::getElapsedTime)
                .gt(WorkOrder::getId, lastId)
                .eq(WorkOrder::getStatus, WorkOrderStatusEnum.TO_PROCESS.getStatus())
                .orderByAsc(WorkOrder::getId)
                .last("limit " + limit)
                .list();
    }

    /**
     * 获取首页工单统计数量
     * @param csId
     * @return
     */
    public CsWorkOrderCountRespVO getHomeCount(Long csId){
        Date currentTime = new Date();
        Date startTime = DateUtil.beginOfDay(currentTime);
        Date endTime = DateUtil.endOfDay(currentTime);
        Long createdCount = this.lambdaQuery().eq(WorkOrder::getCreatorId, csId)
                .between(WorkOrder::getCreateTime, startTime, endTime).count();
        Long processedOrderCount = this.lambdaQuery().eq(WorkOrder::getDesigneeId, csId)
                .between(WorkOrder::getUpdateTime, startTime, endTime).count();
        return CsWorkOrderCountRespVO.builder().createdOrderCount(createdCount).processedOrderCount(processedOrderCount).build();
    }
}
